package com.itlong.cloud.rabbitmq.consumer;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.itlong.cloud.POJO.DTO.common.IotPubMessageDTO;
import com.itlong.cloud.POJO.DTO.smartcard.*;
import com.itlong.cloud.POJO.PO.SmartCardPullPO;
import com.itlong.cloud.POJO.PO.TimeTaskDeadMessageQueuePO;
import com.itlong.cloud.POJO.VO.property.AppUserGetDeviceAuthVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.common.network.tcp.mina.IMinaServiceClient;
import com.itlong.cloud.constants.RabbitMQConstant;
import com.itlong.cloud.constants.RedisConstant;
import com.itlong.cloud.enumerate.*;
import com.itlong.cloud.rabbitmq.config.MessageSender;
import com.itlong.cloud.service.ICloudElevatorChangeBusinessService;
import com.itlong.cloud.service.IMinaService;
import com.itlong.cloud.service.ISmartCardSyncDataPullService;
import com.itlong.cloud.service.RedisService;
import com.itlong.cloud.utils.date.DateUtil;
import com.itlong.cloud.utils.node.JsonUtil;
import com.itlong.cloud.utils.random.LogicIdUtil;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import com.rabbitmq.client.Channel;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.*;


/**
 * <desc>
 *      与旺龙一卡通对接-存储地址数据业务操作队列消费者
 * </desc>
 *
 * @createDate 2017/11/1
 */
@Component
public class SmartCardSaveModifyConsumer {


    private static final Logger LOG = LoggerFactory.getLogger(SmartCardSaveModifyConsumer.class);

    @Value("${" + PlatformConstants.IOT_SMART_CARD_PRODUCT_KEY + "}")
    private  String smartCardIotProductKey; //一卡通产品KEY

    @Autowired
    private IMinaServiceClient iMinaServiceClient;

    @Autowired
    ISmartCardSyncDataPullService iSmartCardSyncDataPullService;

    @Autowired
    ICloudElevatorChangeBusinessService iCloudElevatorChangeBusinessService;

    @Autowired
    MessageSender messageSender;

    @Autowired
    RedisService redisService;

    @Autowired
    IMinaService iMinaService;


    /**
     * <desc>
     *      与旺龙一卡通对接-存储修改的数据业务操作队列消费者
     * </desc>
     * @param message 消息
     * @param channel
     * @return
     * @author zhangs
     * @createDate 2017/10/13
     */
    @RabbitListener(queues = RabbitMQConstant.RABBITMQ_SMARTCARD_SAVE_MODIFY_QUEUE)
    public void process(Message message, Channel channel) throws InterruptedException, IOException{
        byte[] body = message.getBody();
//        LOG.info("RabbitMQ_与旺龙一卡通对接-存储修改的数据业务操作队列消费端:"+body);
        try {

            TimeTaskDeadMessageQueuePO timeTaskDeadMessageQueuePO = JSON.parseObject(new String(body), TimeTaskDeadMessageQueuePO.class);
            //解析项目中各处地址数据更改点传输过来的数据

           SmartCardSyncDataPullDTO smartCardSyncDataPullDTO
                   = JSON.parseObject(JSON.parseObject(timeTaskDeadMessageQueuePO.getMessageContent()).getString("data"),
                   SmartCardSyncDataPullDTO.class);
//            SmartCardSyncDataPullDTO smartCardSyncDataPullDTO =
//                    JSON.parseObject(timeTaskDeadMessageQueuePO.getMessageContent(), SmartCardSyncDataPullDTO.class);


           this.handleSmartCardSyncDataPullDTO(smartCardSyncDataPullDTO);

        } catch (Exception e) {
            channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
            LOG.error("【RabbitMQ_与旺龙一卡通对接-存储修改的数据业务操作队列消费端】:解析异常",e);
        } finally {
            //手动确认消息消费成功。
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        }
    }



    /**
    * <desc>
    *       处理需要同步给一卡通的数据.
    * </desc>
    *
    * @param  smartCardSyncDataPullDTO 与旺龙一卡通对接-存储云端修改数据得数据传输对象
    * @author LewisLouis
    * @createDate 2017-12-20
    */
    private void handleSmartCardSyncDataPullDTO(SmartCardSyncDataPullDTO smartCardSyncDataPullDTO) throws Exception{
       // List<SmartCardSyncDataEquipDTO> smartCardSyncDataEquipDTOS = JSON.parseArray(data, SmartCardSyncDataEquipDTO.class);
        SmartCardSyncDataTypeEnum dataType = smartCardSyncDataPullDTO.getDataType();
        String projectId = smartCardSyncDataPullDTO.getProjectId();
//        String tableName = String.format("%s%s",PlatformConstants.SMARTCARD_TABLENAME_PREFIX_PULL,projectId);
        System.out.println(String.format("一卡通同步消费:%s %s",projectId,dataType.getDescription()));
        switch (dataType){
            case USER_BASIS_DATA:
                List<SmartCardSyncDataPullUserBasisInfoDTO> userBasisInfoDTOS = JSON.parseArray(smartCardSyncDataPullDTO.getData(),
                        SmartCardSyncDataPullUserBasisInfoDTO.class);
                for (SmartCardSyncDataPullUserBasisInfoDTO basisInfoDTO : userBasisInfoDTOS){
//                    SmartCardSyncDataPullUserBasisInfoDTO smartCardSyncDataPullUserBasisInfoDTO
//                     = getSmartCardSyncDataPullUserBasisInfoDTO(projectId,userId);
                    this.handleOneTypeSmartCardSyncData(basisInfoDTO, basisInfoDTO.getDataUid(),
                                dataType, projectId,smartCardSyncDataPullDTO.getDataOperType());

                }
                break;
            case EQUIP_DATA:
                List<SmartCardSyncDataPullEquipDTO> smartCardSyncDataPullEquipDTOS = JSON.parseArray(smartCardSyncDataPullDTO.getData(),
                        SmartCardSyncDataPullEquipDTO.class);
                for (SmartCardSyncDataPullEquipDTO smartCardSyncDataPullEquipDTO:smartCardSyncDataPullEquipDTOS){

                    Integer deviceType = StringHandlerUtil.strToIntDef(StringHandlerUtil.copySubStr(smartCardSyncDataPullEquipDTO.getDeviceUnique(),8,1),0);
                    if(deviceType == PropertyEquipTypeEnum.ENTRANCE.getType()){
                        smartCardSyncDataPullEquipDTO.setDeviceType(PropertyEquipTypeEnum.ENTRANCE.getType());
                    }else{
                        Integer elevtaorType = iCloudElevatorChangeBusinessService.findElevatorTypeByDeviceUnique(smartCardSyncDataPullEquipDTO.getDeviceUnique());
                        if(elevtaorType == PropertyEquipTypeEnum.CLOUD_ELEVATOR.getType()){
                            smartCardSyncDataPullEquipDTO.setDeviceType(4);
                        }else{
                            smartCardSyncDataPullEquipDTO.setDeviceType(PropertyEquipTypeEnum.ELEVATOR.getType());
                        }
                    }

                    this.handleOneTypeSmartCardSyncData(smartCardSyncDataPullEquipDTO, smartCardSyncDataPullEquipDTO.getDataUid(),
                            dataType, projectId,smartCardSyncDataPullDTO.getDataOperType());
                }
                break;
            case USER_AUTH_DATA:
                List<SmartCardSyncDataTmpAuthDTO> smartCardSyncDataTmpAuthDTOS = JSON.parseArray(smartCardSyncDataPullDTO.getData(),
                        SmartCardSyncDataTmpAuthDTO.class);
                for (SmartCardSyncDataTmpAuthDTO smartCardSyncDataTmpAuthDTO : smartCardSyncDataTmpAuthDTOS){
                    SmartCardSyncDataPullUserAuthDTO smartCardSyncDataPullUserAuthDTO
                            = getSmartCardSyncDataPullUserAuthDTOBySmartCardSyncDataTmpAuthDTO(smartCardSyncDataTmpAuthDTO);
                    this.handleOneTypeSmartCardSyncData(smartCardSyncDataPullUserAuthDTO, smartCardSyncDataPullUserAuthDTO.getDataUid(),
                                dataType, projectId, smartCardSyncDataPullDTO.getDataOperType());


                }
                break;

            case PASS_RECORD_DATA:
                List<SmartCardSyncDataRecordDTO> smartCardSyncDataRecordDTOS = JSON.parseArray(smartCardSyncDataPullDTO.getData(),
                        SmartCardSyncDataRecordDTO.class);
                for (SmartCardSyncDataRecordDTO smartCardSyncDataRecordDTO:smartCardSyncDataRecordDTOS){
                    String currentRecProejctId = StringHandlerUtil.getProjectIdByDeviceUnique(smartCardSyncDataRecordDTO.getDeviceUnique());
                    SmartCardSyncDataPullRecordDTO smartCardSyncDataPullRecordDTO = this.getSmartCardSyncDataPullRecordDTOBySource(smartCardSyncDataRecordDTO);
                    this.handleOneTypeSmartCardSyncData(smartCardSyncDataPullRecordDTO, smartCardSyncDataPullRecordDTO.getDataUid(),
                            dataType, currentRecProejctId,smartCardSyncDataPullDTO.getDataOperType());
                    if (!StringHandlerUtil.compareStrIgnoreCaseWithOutEmpty(currentRecProejctId,projectId)){
                        this.notifySmartCardToSyncData(currentRecProejctId);
                    }
                }
                break;

            case FLOOR_RELATION_DATA:
                List<SmartCardSyncDataElevatorFloorInfoDTO> elevatorFloorConfigPOS = JSON.parseArray(smartCardSyncDataPullDTO.getData(),
                        SmartCardSyncDataElevatorFloorInfoDTO.class);

                    this.handleOneTypeSmartCardSyncData(elevatorFloorConfigPOS, elevatorFloorConfigPOS.get(0).getDeviceUnique(),
                            dataType, projectId, smartCardSyncDataPullDTO.getDataOperType());


                break;
            default:
                LOG.info(String.format("未能处理的推送给一卡通的数据类型,%s",smartCardSyncDataPullDTO));
                break;
        }

        this.notifySmartCardToSyncData(projectId);

    }


   /**
   * <desc>
   *    云端有一卡通相关的数据变化，通知一卡通更新.
   * </desc>
   *
   * @param  projectId 项目Id
   * @return
   * @author LewisLouis
   * @createDate 2018-01-08
   */
    private void notifySmartCardToSyncData(String projectId){
        if (StringUtils.isBlank(projectId)){
            return;
        }
//        SmartCardSyncDataCmdDTO smartCardSyncDataCmdDTO = new SmartCardSyncDataCmdDTO();
//        smartCardSyncDataCmdDTO.setAct(PlatformConstants.SMARTCARD_SYNC_DATA_CMD_ACT);
//        iMinaService.sendMessage(projectId,JSON.toJSONString(smartCardSyncDataCmdDTO));

        this.sendIotMessage(projectId);
    }

    /**
     * <desc>
     *     查询App用户项目基本信息-.
     * </desc>
     *
     * @param  projectId 项目Id
     * @param  userId 用户Id
     * @return 查询结果
     * @author LewisLouis
     * @createDate 2017-12-22
     */
    private SmartCardSyncDataPullUserBasisInfoDTO getSmartCardSyncDataPullUserBasisInfoDTO(
            String projectId,String userId){
        if (StringUtils.isBlank(userId)) {
            return null;
        }
        List<SmartCardSyncDataPullUserBasisInfoDTO> smartCardSyncDataPullUserBasisInfoDTOS
                = iSmartCardSyncDataPullService.getUserBasisInfo(projectId,userId);

        if ((null == smartCardSyncDataPullUserBasisInfoDTOS) || (smartCardSyncDataPullUserBasisInfoDTOS.isEmpty())){
            return null;
        }
        return smartCardSyncDataPullUserBasisInfoDTOS.get(0);
    }


    /**
     * <desc>
     *     转换为同步所需的通行记录数据格式.
     * </desc>
     *
     * @param  smartCardSyncDataRecordDTO  与旺龙一卡通对接-通行记录信息解析传输对象
     * @return 与旺龙一卡通对接-通行记录信息传输对象(用于存储通行记录信息数据进pull表最终推送给一卡通)
     * @author LewisLouis
     * @createDate 2017-12-29
     */
    private SmartCardSyncDataPullRecordDTO getSmartCardSyncDataPullRecordDTOBySource(SmartCardSyncDataRecordDTO smartCardSyncDataRecordDTO){
        SmartCardSyncDataPullRecordDTO smartCardSyncDataPullRecordDTO = new SmartCardSyncDataPullRecordDTO();
        String phoneInfo = smartCardSyncDataRecordDTO.getUserPhone();
        if (StringUtils.isNotBlank(phoneInfo) && StringHandlerUtil.isEmail(phoneInfo)){
            smartCardSyncDataPullRecordDTO.setUserEmail(smartCardSyncDataRecordDTO.getUserPhone());
        } else{
            smartCardSyncDataPullRecordDTO.setUserPhone(smartCardSyncDataRecordDTO.getUserPhone());
        }
        smartCardSyncDataPullRecordDTO.setDeviceUnique(smartCardSyncDataRecordDTO.getDeviceUnique());
        smartCardSyncDataPullRecordDTO.setPassTime(String.valueOf(smartCardSyncDataRecordDTO.getPassTime().getTime()));
        smartCardSyncDataPullRecordDTO.setPassType(smartCardSyncDataRecordDTO.getOpenType());
        smartCardSyncDataPullRecordDTO.setDeviceType(
                StringHandlerUtil.strToIntDef(StringHandlerUtil.copySubStr(smartCardSyncDataRecordDTO.getDeviceUnique(),8,1),0));
        return smartCardSyncDataPullRecordDTO;
    }


    /**
    * <desc>
    *     转换为同步所需的用户权限数据格式.
    * </desc>
    *
    * @param  smartCardSyncDataTmpAuthDTO  与旺龙一卡通对接-住户设备权限信息传输对象
    * @return 与旺龙一卡通对接-住户设备权限信息传输对象(用于存储住户设备权限信息数据进pull表最终推送给一卡通)
    * @author LewisLouis
    * @createDate 2017-12-29
    */
     private SmartCardSyncDataPullUserAuthDTO getSmartCardSyncDataPullUserAuthDTOBySmartCardSyncDataTmpAuthDTO(
             SmartCardSyncDataTmpAuthDTO smartCardSyncDataTmpAuthDTO) throws Exception {
         String userId = smartCardSyncDataTmpAuthDTO.getUserId();
         String userPhone = iSmartCardSyncDataPullService.getUserPhoneByUserId(userId); //smartCardSyncDataTmpAuthDTO.getUserPhone();//  //iPropertyHouseHoldInfoServiceClient.getUserPhone(userId);
         //设备有效期
         String validDate = String.valueOf(DateUtil.fomatLongDate("2099-12-31 23:59:59").getTime());

         //所有设备权限列表
         List<AppUserGetDeviceAuthVO> allDeviceAuthList = smartCardSyncDataTmpAuthDTO.getAppUserGetDeviceAuthVOS();

         //系统（电梯、门禁）设备权限信息传输对象集
         List<SmartCardSyncDataSysDeviceAuthDTO> smartCardSyncDataSysDeviceAuthDTOS = new ArrayList<>();

         //格式化数据
         //Map用于拼接设备权限码集<deviceType,List<SmartCardSyncDataSingleDevieAuthDTO>>
         Map<String, List<SmartCardSyncDataSingleDevieAuthDTO>> deviceAuthMap = new HashMap<>();
         //遍历用户的设备权限
         for(AppUserGetDeviceAuthVO appUserGetDeviceAuthVO:allDeviceAuthList) {
             String deviceUnique = appUserGetDeviceAuthVO.getDeviceUnique();
             String naturalFloor = appUserGetDeviceAuthVO.getNaturalFloor();
             String deviceType = appUserGetDeviceAuthVO.getDeviceType();
             String auth = "";
             //判断设备类型，转换权限码
             if(!StringHandlerUtil.compareStrWithOutEmpty(
                     String.valueOf(PropertyEquipTypeEnum.ELEVATOR.getType()), deviceType)) {
                 auth = PlatformConstants.ENTRANCE_AUTHNUM;
             } else {
                 auth = StringHandlerUtil.getAuthCodeBynNturalFloors(naturalFloor);
             }
             //设备权限码数据传输对象
             SmartCardSyncDataSingleDevieAuthDTO smartCardSyncDataSingleDevieAuthDTO =
                     new SmartCardSyncDataSingleDevieAuthDTO(deviceUnique, auth);
             //设备权限码数据传输对象集
            // List<SmartCardSyncDataSingleDevieAuthDTO> smartCardSyncDataSingleDevieAuthDTOS = new ArrayList<>();
             //整理设备权限码集
             List<SmartCardSyncDataSingleDevieAuthDTO> smartCardSyncDataSingleDevieAuthDTOS = deviceAuthMap.get(deviceType);
             if(smartCardSyncDataSingleDevieAuthDTOS == null) {
                 smartCardSyncDataSingleDevieAuthDTOS = new ArrayList<>();
                 smartCardSyncDataSingleDevieAuthDTOS.add(smartCardSyncDataSingleDevieAuthDTO);
                 deviceAuthMap.put(deviceType, smartCardSyncDataSingleDevieAuthDTOS);
             } else {
                 smartCardSyncDataSingleDevieAuthDTOS.add(smartCardSyncDataSingleDevieAuthDTO);
             }

         }
         Set<String> deviceTypeSet = deviceAuthMap.keySet();
         //拼接设备权限信息 SmartCardSyncDataSysDeviceAuthDTO
         for (String deviceType : deviceTypeSet) {
             //设备权限码数据传输对象集
             List<SmartCardSyncDataSingleDevieAuthDTO> smartCardSyncDataSingleDevieAuthDTOS = deviceAuthMap.get(deviceType);
             //设备权限信息传输对象
             SmartCardSyncDataSysDeviceAuthDTO smartCardSyncDataSysDeviceAuthDTO = new SmartCardSyncDataSysDeviceAuthDTO();
             smartCardSyncDataSysDeviceAuthDTO.setDeviceAuths(smartCardSyncDataSingleDevieAuthDTOS);
             smartCardSyncDataSysDeviceAuthDTO.setDeviceType(Integer.parseInt(deviceType));
             smartCardSyncDataSysDeviceAuthDTO.setValidDate(validDate);
             smartCardSyncDataSysDeviceAuthDTOS.add(smartCardSyncDataSysDeviceAuthDTO);
         }
         //住户设备权限信息传输对象
         SmartCardSyncDataPullUserAuthDTO smartCardSyncDataPullUserAuthDTO = new SmartCardSyncDataPullUserAuthDTO();
         smartCardSyncDataPullUserAuthDTO.setUserPhone(userPhone);
         smartCardSyncDataPullUserAuthDTO.setSysAuths(smartCardSyncDataSysDeviceAuthDTOS);
         return smartCardSyncDataPullUserAuthDTO;
     }
    /**
    * <desc>
    *    处理单个同步给一卡通的数据.
    * </desc>
    *
    * @param data 单个同步数据对象
    * @return xx
    * @author LewisLouis
    * @createDate 2017-12-21
    */
    private void handleOneTypeSmartCardSyncData(Object data,String dataUid, SmartCardSyncDataTypeEnum dataType,
                                                String projectId,SmartCardSyncDataOperTypeEnum dataOperType){
        if (StringUtils.isBlank(projectId)){
            LOG.info(String.format("准备推送给一卡通的数据非法:%s", JSON.toJSONString(data)));
            return;
        }
        String tableName = String.format("%s%s", PlatformConstants.SMARTCARD_TABLENAME_PREFIX_PULL, projectId);

        SmartCardPullPO smartCardPullPO = new SmartCardPullPO();
        smartCardPullPO.setDataUid(dataUid);
        smartCardPullPO.setDataType(dataType.getType());
        //先根据DataUid和DataType进行查询
        List<SmartCardPullPO> smartCardPullPOS = iSmartCardSyncDataPullService.getPullData(tableName, smartCardPullPO);


        smartCardPullPO.setSyncStatus(SmartCardSyncDataStatusEnum.NOT_SYNC.getType());
        smartCardPullPO.setProjectId(projectId);
        smartCardPullPO.setSyncData(JSON.toJSONString(data));
        smartCardPullPO.setDataOperType(dataOperType.getType());
        smartCardPullPO.setSyncSerialNo(LogicIdUtil.randomUUID());
        smartCardPullPO.setStatus(DataStatusEnum.NORMAL.getType());
        smartCardPullPO.setDataType(dataType.getType());
        Date date = new Date();

        if ((smartCardPullPOS == null) || (smartCardPullPOS.isEmpty())) {
            smartCardPullPO.setCreateTime(date);
            smartCardPullPO.setUpdateTime(date);
            iSmartCardSyncDataPullService.savePullData(tableName, smartCardPullPO);
        } else {
            smartCardPullPO.setUpdateTime(date);
            smartCardPullPO.setId(smartCardPullPOS.get(0).getId());
            iSmartCardSyncDataPullService.updatePullData(tableName, smartCardPullPO);
        }
    }

    /**
     * <desc>
     *      处理推送设备指令转换为iot指令
     * </desc>
     *
     * @param projectId 项目编号
     * @author Qiang.S
     * @createDate 2019/07/25
     */
    private void sendIotMessage (String projectId) {
        try {
            //过滤离线设备
            if (!StringUtils.isBlank(redisService.get(RedisConstant.DEVICE_SMART_CARD_IS_ONLINE_KEY + projectId))) {
                List<Map<String, Object>> messages = new ArrayList<>();
                //iot指令准备
                Map<String, Object> message = new HashMap<>();
                message.put("productKey", smartCardIotProductKey);
                message.put("topic", "/" + projectId + "/user" + IotCloudCtrlInstructEnum.DEVICECMD.getUrl());
                IotPubMessageDTO dto = new IotPubMessageDTO();
                dto.setSourceForm("itlong");
                dto.setCmd("1001");
                dto.setSnr(0);
                message.put("message", JsonUtil.toJSON(dto));
                messages.add(message);
                this.sendCloudIotMessage(messages);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * <desc>
     *      发布消息到iot中心
     * </desc>
     *
     * @param messages
     * @author Qiang.S
     * @createDate 2019/07/04
     */
    private void sendCloudIotMessage(List<Map<String,Object>> messages) throws Exception {
        if(!messages.isEmpty()){
            Map<String,Object> params = new HashMap<>();
            params.put("deviceOperateIotType", DeviceIotEnum.PUB_MESSAGE.getCommandType());
            params.put("devices",messages);
            JSONObject obj = new JSONObject();
            obj.put("data",params);
            messageSender.send(RabbitMQConstant.RABBITMQ_IOT_PUB_QUEUE, obj.toJSONString(),
                    RabbitMQConstant.RABBITMQ_IOT_PUB_EXCHANGE, RabbitMQConstant.RABBITMQ_IOT_PUB_KEY);
        }
    }

}
